package com.htdata.iiot;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.alibaba.fastjson.JSONObject;
import com.htdata.iiot.api.pojo.Metric;
import com.htdata.iiot.api.pojo.RestStreamingData;
import com.htdata.iiot.api.pojo.RestStreamingMetricData;
import com.htdata.iiot.db.DbConnectionPool;
import com.htdata.iiot.db.JDBCUtils;
import com.htdata.iiot.utils.FileUtils;
import com.htdata.iiot.utils.Post;
import com.htdata.iiot.utils.RandomDate;

/**
 * 从数据库中读取测点的取值范围，只有min表示固定值
 * 
 */
public class Main2Rest {
	private static Logger logger = LogManager.getLogger(Main2Rest.class);
	private static DbConnectionPool pool;
	private static String tenantIds;
	private static int times=60;
	private static Map<String, Metric> dnTometric = new HashMap<>();

	public static void main(String[] args) throws ParseException {
		Cmd.parserCmd(args);
		tenantIds = Cmd.tenantIds;
		times = Cmd.times;
		Post post = null;
		if(Cmd.url!=null){
			post = new Post(Cmd.url);
		}else{
			System.out.println("url not config");
			System.exit(0);
		}
		
		pool  = DbConnectionPool.getPool();
		List<RestStreamingData> sList = new ArrayList<RestStreamingData>();
		// 1.根据租户ID获取租户、设备

		String sql1 = " select * from (SELECT  T2.* FROM" 
		+ "  (SELECT" 
				+ "    T.*," 
				+ "    CASE" 
				+ "      WHEN @mid = struct_id"
				+ "      THEN @row := @row + 1" 
				+ "      ELSE @row := 1" 
				+ "    END rownum,"
				+ "    @mid := struct_id MID" 
				+ "  FROM" 
				+ "    (SELECT" 
				+ "      struct_id," 
				+ "      id,serial_number,tenant_id,"
				+ "      SUM(1)" 
				+ "    FROM" 
				+ "      thing_device" 
				+ "      WHERE"
				+ "        deleted=0 AND TYPE=0" 
				+ "    GROUP BY struct_id,id,serial_number,tenant_id"
				+ "    ORDER BY struct_id,id," 
				+ "      SUM(1) DESC) AS T) AS T2 ) t " ;
		if(tenantIds!=null&&!tenantIds.trim().isEmpty()){
			sql1+=" where `tenant_id` in("+tenantIds+") ";
		}
		
		if(Cmd.pageSize>0){
			sql1 += "ORDER BY rownum,id " + "LIMIT 0,"+Cmd.pageSize+" ";
		}

		String sql = "SELECT t.api_key,d.* FROM tenant t,("+sql1+") d WHERE t.id=d.tenant_id";
		logger.info(sql);
		Connection conn = pool.getConnection();
		PreparedStatement ps = null;
		ResultSet rs = null;
		ResultSet executeQuery = null;
		PreparedStatement prepareStatement = null;
		try {
			ps = conn.prepareStatement(sql);
			rs = ps.executeQuery();
			while (rs.next()) {
				String sn = rs.getString("serial_number");
				String ak = rs.getString("api_key");
				int tenantId = rs.getInt("tenant_id");
				int deviceId = rs.getInt("id");

				RestStreamingData streamingData = new RestStreamingData();
				streamingData.setAccesskey(ak);
				streamingData.setEquipment(sn);
				streamingData.setIot(tenantId);
				// 2.根据设备获取测点
				String sql2 = "SELECT" + "  t1.id AS id," + "  t2.`name` AS name,t2.min AS valueMin,t2.max AS valueMax,"
						+ "  t3.`name` AS componentname,"
						+ "  t4.`name` AS devicename" + " FROM" + "  `thing_device_component_rel` t1,"
						+ "  `thing_data_stream` t2," + "  thing_component t3," + "  `thing_device` t4"
						+ " WHERE t1.`component_id` = t3.`id`" + "  AND t3.deleted = 0"
						+ "  AND t2.`component_id` = t3.`id`" + "  AND t1.deleted = 0" + "  AND t1.device_id = ?"
						+ "  AND t2.deleted = 0" + "  AND t2.tenant_id = ?" + "  AND t4.id = t1.`device_id`";
				prepareStatement = conn.prepareStatement(sql2);
				prepareStatement.setInt(1, deviceId);
				prepareStatement.setInt(2, tenantId);
				executeQuery = prepareStatement.executeQuery();
				List<RestStreamingMetricData> mList = new ArrayList<RestStreamingMetricData>();
				while (executeQuery.next()) {
					String name = executeQuery.getString("name");
					long mId = executeQuery.getLong("id");
					RestStreamingMetricData metricData = new RestStreamingMetricData();
					metricData.setK(name);
					String deviceName = executeQuery.getString("devicename"); //设备名
					String componentname = executeQuery.getString("componentname");   //测点名
					Double valueMin = executeQuery.getDouble("valueMin");
					Double valueMax = executeQuery.getDouble("valueMax");
					dnTometric.put(streamingData.getIot()+"_"+streamingData.getAccesskey()+"_"+streamingData.getEquipment()+"_"+metricData.getK(), new Metric(mId,tenantId,deviceId, deviceName, componentname,name,valueMin,valueMax));

					mList.add(metricData);
				}
				streamingData.setData(mList);
				if (mList.size() > 0) {
					sList.add(streamingData);
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.close(ps, rs, conn);
			JDBCUtils.close(prepareStatement, executeQuery, null);
		}

		logger.info("****************************");
		logger.info(sList.size());
		logger.info("****************************");
		long startTime = System.currentTimeMillis() - 1;
		long st = System.currentTimeMillis();
		long i = 0;
		long mi = 0;
		Object value = null;
		long avg = sList.size();
		if(times!=0){
			avg = sList.size()/(times*2);
		}
		if(avg == 0){
			avg = sList.size();
		}
		
		while (true) {
			st = System.currentTimeMillis();
			long tsz = System.currentTimeMillis();
			// 3.生成数据
			for (RestStreamingData sData : sList) {
				value = null;
				List<RestStreamingMetricData> data = sData.getData();
				for (RestStreamingMetricData mData : data) {
					value = FileUtils.getValueRangeFromMetric(dnTometric.get(sData.getIot()+"_"+sData.getAccesskey()+"_"+sData.getEquipment()+"_"+mData.getK()));
					mData.setV(value);
					mData.setT(System.currentTimeMillis());
					mi++;
				}

				if (value != null) {
					post.SendPost(buildResult(sData));
					i++;
				}
				if(i%avg==0){
					//线程休息
					long now = System.currentTimeMillis();
					try {
						if(now<(tsz+500)){
							logger.info("中场休息"+"i:"+i);
							Thread.sleep(tsz+500-now);
						}else{
							logger.info("中场超时"+"i:"+i);
						}
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					tsz = System.currentTimeMillis();
				}
			}
			
			long endTime = System.currentTimeMillis();
			long useTime = endTime - startTime;
			logger.info(st+"写入 " + i + " 条数据,累计测点数：" + mi + "，平均速率 " + (i * 1000 / useTime) + "，测点速率 "
					+ (mi * 1000 / useTime));
			if(endTime<(st+times*1000)){
				try {
					logger.info("本场结束");
					Thread.sleep(st+times*1000-endTime);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}else{
				logger.info("本场超时");
			}

		}

	}

	private static String buildResult(RestStreamingData sData) {
		return JSONObject.toJSONString(sData).toString();
	}

}